<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="jquery.js" charset="utf-8"></script>
    <script>

        // ajax的基础用法
        $.ajax({
            url:'data/arr.txt',  //url 请求地址
            method:'get',  // method  存放请求方法，get post
            data:{},  //data 请求成功后返回的数据
            success:function(res){
                console.log(18,res) //success 成功时调用的方法
            },
            error:function(err){
                console.log(21,err) //error 失败时调用的方法
            }
        })
    // 回调地狱    
        //定义： 后面的数据依赖于前面的一层数据，依赖层数太多，就会产生地狱回调的问题，代码复杂，不优雅。

        // 缺点: 代码耦合性太强，牵一发动全身，难以维护。
            //  大量冗余的代码相互嵌套，可读性变差。
        
        // 解决地狱回调
            // 1.声明全局变量
            function promise(){
                var a1=''
                $.ajax({
                    url:'data/1.json',
                    success:function(res){
                        console.log(res) 
                        a1=res.a
                        console.log('a1的结果执行了')
                    }
                }) 
                return a1
                console.log(42,a1);
            }
                //把a1拿到外面，使用
                let p=promise()
                console.log(47,p)
                //下面多个接口在调用 ，就可以用这个值了

        // 问题：全局变量会污染内存环境
        
            //2.回调函数
            function promise1(cb){
                
                $.ajax({
                    url:'data/1.json',
                    success:function(res){
                        // console.log(res) 
                        var a1=res.a;
                        console.log('a1的结果执行了')
                        //用回调函数，把结果返回出去
                        cb(a1)
                    }
                }) 
            }
            //回调函数执行，接收里面的结果
            promise1(function(b){
                console.log(67,b)
            })
            
    // promise
        // es6中new Promise() 作用把异步操作改成同步执行
        // console.dir(Promise) 可查看对象上的所有属性与方法
    // 基础用法
                        
        let p=new Promise((resolve,reject)=>{
		//内部放异步请求的内容 ajax ,成功的通过resolve回调出去,失败的通过reject回调出去
		//   resolve('成功了')  //状态由pending变为fulfilled
		  reject('失败了')     //状态由pending变为rejected
	    })
	    //then里面是方法，代表请求成功或失败执行的回调

        //方法1
        // console.log('18三种状态',p)  //promise返回的是一个对象
        // p.then((res)=>{ //成功回调
        // console.log(20,res)
        // },(err)=>{ //失败回调
        // console.log(22,err)
        // }) 

         //方法2
        // p.then((res)=>{ //成功回调
        //         console.log('成功回调',res)
        // }).catch((err)=>{ //失败回调
        //         console.log('失败回调',err)
        // }).finally(()=>{
        //     console.log('finally中不管成功失败都会执行');
        // })  

        //promise里面放网络请求，把异步请求结果变成链式调用执行

    // ajax请求数据-成功或者失败方法是在内部执行的。如果请求成功的数据外面要用时，外面是拿不到的，因为它是一个函数。
        //  $.ajax({
        // 	url:'data/arr.txt',
        // 	success:function(res){
        // 		console.log(36,res) //成功
        // 	},
        // 	error:function(err){
        // 		console.log(err) //失败
        // 	}
        // }) 
        
    // 用promise包装网络ajax请求,两个参数其实是回调名字
        let p =	new Promise((cb,cb2)=>{
                $.ajax({
                url:'data/arr.txt',
                success:function(res){
                    console.log(res) //成功
                    cb(res) //成功的回调
                },
                error:function(err){
                    console.log(err) //失败
                    cb2(err) //失败的回调
                }
            }) 
        })
        //用法1  在then里面用两个箭头函数来返回，res成功 err失败
        console.log(p);
        p.then((res)=>{
            console.log('成功的结果',res);
        },
        (err)=>{
            console.log('失败的结果',err);
        })
        //用法2  then，catch
        // p.then((res)=>{
        // 	console.log('成功的结果',res);
        // }).catch((err)=>{
        // 	console.log('失败的结果',err);
        // }) 
        
        // promise可把异步的执行改成同步。把请求成功的数据，通过回调函数拿到外面执行
        var p=new Promise(function(resolve,reject){
		 //需要的异步请求
		 $.ajax({
		 	url:'data/arr.txt',
		 	success:function(res){
		 		resolve(res) 
		 	},
		 	error:function(err){
		 		reject(err) 
                    }
                })
            })	
            //then可以把异步执行弄成同步执行
            console.log(p) //返回的对象里面有then方法
            p.then(function(res){
                console.log('成功结果',res)
            }).catch(function(err){
                console.log('失败结果',err)
            })
        //工作中接口地址会经常改变，可用函数把promise再次封装，外面传入接口地址。其实就是大家常用的axios的原理，内部封装。
            // axios的原理是内部封装
            function axios(url2){
                return new Promise(function(resolve,reject){
                            $.ajax({
                                url:url2,     //通过传参来写接口
                                success:function(res){
                                    resolve(res) 
                                },
                                error:function(err){
                                    reject(err) 
                                }
                            })
                        })	
                    }
                var p2= axios('data/1.json',) 
                p2.then(function(res){
                    console.log(res)
                },function(err){
                    console.log(err)
                })
        //  ajax请求多个数据，如果后面数据依赖前面数据-会有痛点，产生回调地狱问题
        
	//3.2 Promise解决回调地狱问题
	    //通过promise封装ajax方法
    /* function getAjax(url2){
    		return new Promise(function(resolve,reject){
    			 $.ajax({
    			 	url:url2, //url可通过外面传入
    			 	success:function(res){
    			 		resolve(res) 
    			 	},
    			 	error:function(err){
    			 		reject(err) 
    			 	}
    			 })
    		 })	
    		  
    	}
      var arr=getAjax('data/arr.txt')   //同步执行
	  var arr2=getAjax('data/num.txt')  //同步执行
	  arr.then((res)=>{
		  console.log(res)
	    var data=eval(res)  //把字符串转成原始数据	
		 let data=JSON.parse(res)
		 data.push('我是新添加的')
		 console.log(data)
            if(data){
                arr2.then((res1)=>{
                    console.log(res1)
            })
	    }
	  }).catch(err=>{
		  console.log('失败了',err);
	  })  */

      //多个请求也可用 Promise.all()方法-返回的是数组，需要展开下拿到每个值。有一个失败，都会失败。应用场景：需要同时请求多个数据接口，只有全部请求成功，才会在页面上展示数据
      let p1=	new Promise(function(resolve,reject){
    			 $.ajax({
    			 	url:'data/json.txt', //url可通过外面传入
    			 	success:function(res){
    			 		resolve(res) //成功回调
    			 	},
    			 	error:function(err){
    			 		reject(err) //失败回调
    			 	}
    			})
    		})	
	let p2=	new Promise(function(resolve,reject){
		$.ajax({
		url:'data/arr.txt', //url可通过外面传入
		success:function(res){
			resolve(res) //成功回调
		},
		error:function(err){
			reject(err) //失败回调
		}
		})
		
	})	
	 Promise.all([
		 //可以把promise封装下getAjax()方法
		    //  getAjax('data/json.txt'),
		    //  getAjax('data/arr.txt'),
		p1,p2
	    ]).then(
		   function(res){
			   console.log('返回合并后的数组',res);
			   var [a,b]=res
			  console.log('全成功了',a,b)
			},
		   function(err){
			   console.log('有一个失败全失败',err)
		   }
	  )	
      
    /*
        什么是promise？
            解决地狱回调问题
            它可以进行链式调用
            
        有三种状态分别是
            pending 初始状态,进行中 
            fulfilled 成功状态，请求成功了 
            rejected 失败状态，请求失败了  
            
        Promise的状态一旦改变，就不会再变，任何时候都可以得到这个结果，状态不可以逆，只能由 pending变成fulfilled或者由pending变成rejected。

        promise的API方法：.then(),.catch(),.finally()，.all(),.race()

        promise应用场景：封装ajax,axios的get,post封装，微信小程序中封装wx.request()，uniapp开发中uni.request()
    */

    </script>
</head>
<body>
    
</body>
</html>